/**
 * 异常 https://book.kotlincn.net/text/exceptions.html
 */

/**
 * 异常类
 */
fun main121() {
    //Kotlin 中所有异常类继承自 Throwable 类。 每个异常都有消息、堆栈回溯信息以及可选的原因。
    //使用 throw 表达式来抛出异常：
    throw Exception("Hi There!")

    /**
     * 使用 try……catch 表达式来捕获异常：
     * 可以有零到多个 catch 块，finally 块可以省略。 但是 catch 与 finally 块至少需有一个。
     */
    try {
        // 一些代码
    } catch (e: Exception) {
        // 处理程序
    } finally {
        // 可选的 finally 块
    }
}

/**
 * Try 是一个表达式
 */
fun main122() {
    /**
     * try 是一个表达式，意味着它可以有一个返回值：
     * try-表达式的返回值是 try 块中的最后一个表达式或者是（所有）catch 块中的最后一个表达式。 finally 块中的内容不会影响表达式的结果。
     */
    val input = "123"
    val a: Int? = try { input.toInt() } catch (e: NumberFormatException) { null }
}


/**
 * Nothing 类型
 */
fun main() {
    val name = "Test"
    /**
     * 1.在 Kotlin 中 throw 是表达式，所以你可以使用它（比如）作为 Elvis 表达式的一部分：
     */
    val s = name ?: throw IllegalArgumentException("Name required")

    /**
     * 2.throw 表达式的类型是 Nothing 类型。 这个类型没有值，而是用于标记永远不能达到的代码位置。
     *   在你自己的代码中，你可以使用 Nothing 来标记一个永远不会返回的函数：
     */
    fun fail(message: String): Nothing {
        throw IllegalArgumentException(message)
    }
    //当你调用该函数时，编译器会知道在该调用后就不再继续执行了：
    val s2 = name ?: fail("Name required")
    println(s)     // 在此已知“s”已初始化

    /**
     * 3.当处理类型推断时还可能会遇到这个类型。这个类型的可空变体 Nothing? 有一个可能的值是 null。
     *   如果用 null 来初始化一个要推断类型的值，而又没有其他信息可用于确定更具体的类型时，编译器会推断出 Nothing? 类型：
     */
    val x = null           // “x”具有类型 `Nothing?`
    val l = listOf(null)   // “l”具有类型 `List<Nothing?>
}